package cn.whitecao.agent.plugin.handler;

import cn.whitecao.agent.core.handler.PluginAopHandler;
import cn.whitecao.agent.core.model.Span;
import cn.whitecao.agent.core.model.TraceModel;
import cn.whitecao.agent.core.repoter.ReporterProcessor;
import cn.whitecao.agent.core.trace.TraceContext;
import cn.whitecao.agent.core.trace.TraceTag;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author : BashfulHuang
 **/

public class ServletHandler implements PluginAopHandler {
    private Span servletData;

    /**
     * 前置
     *
     * @param className  类名
     * @param methodName 方法名
     * @param args       参数列表
     * @param oThis      可以当this用
     */
    @Override
    public void before(String className, String methodName, Object[] args, Object oThis) {
        Span servletSpan = new Span(Span.DataType.SERVLET);

        //也可能是别的服务调用的,所以先判断下 Header里有没有带过来
        //也需要对okhttp等常见调用库做个切面 自动戴上
        Object arg1 = args[0];
        TraceModel traceModel = TraceContext.create();

        if (arg1 instanceof HttpServletRequest){
            HttpServletRequest request = (HttpServletRequest) arg1;
            String traceId = request.getHeader(TraceTag.TRACE_ID_TAG);
            String parentSpanId = request.getHeader(TraceTag.SPAN_ID);
            //只要traceId是null的话 其他的肯定都是null,就得
            if (traceId!=null) {
                traceModel.setTraceId(traceId);
                traceModel.setParentSpanId(parentSpanId);

                servletSpan.setTraceId(traceId);
                servletSpan.setParentSpanId(parentSpanId);

            }else{
                servletSpan.setTraceId(traceModel.getTraceId());
                servletSpan.setParentSpanId("");

                traceModel.setSpanId(servletSpan.getSpanId());
            }
            servletSpan.setSequenceNumber(traceModel.incAndGetSequenceNumber());
            servletSpan.setAppName(traceModel.getAppName());
            servletSpan.addData("uri",request.getRequestURI());
            //后面的需要处理下ip 使用过nginx这些代理工具的话会返回127.0.0.1
            servletSpan.addData("ip",request.getRemoteAddr());

        }
        this.servletData=servletSpan;
    }

    /**
     * 后置
     *
     * @param className  类名
     * @param methodName 方法名
     * @param args       参数
     * @param result     返回值
     * @param oThis      this
     * @param throwable  抛出的异常
     */
    @Override
    public void after(String className, String methodName, Object[] args, Object result, Object oThis, Throwable throwable) {
        Span model = this.servletData;
        model.calculateExecutionTime();
        if (args.length>1&&args[1] instanceof HttpServletResponse){
            HttpServletResponse response = (HttpServletResponse) args[1];
            model.addData("code",response.getStatus());
        }
        ReporterProcessor.report(model);
        TraceContext.remove();
    }
}
